/**
 * create by zhike
 * date:2015年3月12日
 */
package com.acooly.module.openapi.client.provider.allinpay.marshall;

import com.acooly.core.utils.Reflections;
import com.acooly.core.utils.Strings;
import com.acooly.module.openapi.client.api.exception.ApiClientException;
import com.acooly.module.openapi.client.api.marshal.ApiUnmarshal;
import com.acooly.module.openapi.client.api.message.MessageFactory;
import com.acooly.module.openapi.client.provider.allinpay.AllinpayConstants;
import com.acooly.module.openapi.client.provider.allinpay.OpenAPIClientAllinpayProperties;
import com.acooly.module.openapi.client.provider.allinpay.domain.AllinpayNotify;
import com.acooly.module.openapi.client.provider.allinpay.enums.AllinpayServiceEnum;
import com.acooly.module.openapi.client.provider.allinpay.support.AllinpayAlias;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * @author zhike
 */
@Service
@Slf4j
public class AllinpayNotifyUnmarshall extends AllinpayMarshallSupport
        implements ApiUnmarshal<AllinpayNotify, Map<String, String>> {

    @Resource(name = "allinpayMessageFactory")
    private MessageFactory messageFactory;

    @Autowired
    private OpenAPIClientAllinpayProperties properties;

    @Override
    public AllinpayNotify unmarshal(Map<String, String> message, String serviceName) {
        try {
            //验签异步报文
            if (Strings.equals(serviceName, AllinpayServiceEnum.POS_PAY_NOTIFY.getCode())) {
                log.info("收银宝异步通知{}", message);
                String signature = message.get(AllinpayConstants.SIGN_NAME);
                SortedMap<String, String> sort = new TreeMap<String, String>(message);
                doMd5VerifySign(sort, signature);
            } else {
                log.info("通联通异步通知{}", message);
                AllinpayNotify allinpayNotify = doUnmarshall(message, serviceName);
                String signStr = allinpayNotify.getSignStr();
                doVerifySign(signStr);
            }
            log.info("验签成功");
            return doUnmarshall(message, serviceName);
        } catch (Exception e) {
            throw new ApiClientException("异步通知 解析失败:" + e.getMessage());
        }
    }

    /**
     * 解析异步通知报文
     *
     * @param message
     * @param serviceName
     * @return
     */
    protected AllinpayNotify doUnmarshall(Map<String, String> message, String serviceName) {
        AllinpayNotify notify =
                (AllinpayNotify) messageFactory.getNotify(serviceName);
        Set<Field> fields = Reflections.getFields(notify.getClass());
        String key = null;
        for (Field field : fields) {
            AllinpayAlias wftAlias = field.getAnnotation(AllinpayAlias.class);
            if (wftAlias != null && Strings.isNotBlank(wftAlias.value())) {
                key = wftAlias.value();
            } else {
                key = field.getName();
            }
            Reflections.invokeSetter(notify, field.getName(), message.get(key));
        }
        return notify;
    }
}
